import Authorization.User;
import IO.Output;
import Questions.Question;
import Session.SessionHelper;
import Session.TestSession;
import Session.Results;
import Source.MsgKeys;
import Source.NotificationsStorage;
import Source.QuestionsFactory;
import java.util.Scanner;
import java.io.IOException;

/**
 * Created with IntelliJ IDEA.
 * Authorization.User: Инесса
 * Date: 23.10.13
 * Time: 1:26
 * To change this template use File | Settings | File Templates.
 */
public class Controller {
    NotificationsStorage notification;
    public final int MIN_LEVEL_POINTS=3;

    public Controller(){
        notification = new NotificationsStorage();
    }


    /**
     * Проверка пришел что вернул UserController, если пользователя - начинаем тест, если админа - печатает статистику
     * @param user пользователь для теста
     * @throws IOException
     */
    public void performActions(User user) throws IOException {
        Results results = new Results();
        Output.printLineMsg(notification.getNotification(MsgKeys.HELLO_MSG) + user.getLogin());
        if (!user.getLogin().equals("admin")) {
            notification.notify(MsgKeys.START_TEST_MSG);
            testingUser(user, results);
        } else {
            results.printResultsFromFile();
        }
    }

    /**
     * Метод который и выполняет все тестирование пользователя
     * @param user  пользователь
     * @param results результаты для админа
     * @throws IOException
     */
    void testingUser(User user, Results results) throws IOException {
        Scanner scanner = new Scanner(System.in);
        SessionHelper sessionHelper = new SessionHelper();
        CommandHelper commandHelper = new CommandHelper();
        TestSession testSession;
        boolean hasSession = sessionHelper.hasSession(user);
        boolean createSession = isCreatedSession(scanner, hasSession);
        testSession = getTestSession(user, scanner, sessionHelper, createSession);


        testSession=executeLevel(testSession,commandHelper,scanner);

        while (!testSession.isEnd()&&!commandHelper.isEndExecution()){

        boolean passed=checkLevelPassed(testSession);
        if(passed){
            testSession.addSessionPoints(testSession.countCorrect());
            testSession.flushAnswers();
            testSession.levelUp();
            if(!testSession.isEnd()){
            testSession.setCurrentIndexOfLevel(0);
            testSession=executeLevel(testSession,commandHelper,scanner);
            } else {
                 break;
             }

        } else {
            testSession.flushAnswers();
            testSession.refreshLevel();
            testSession.setCurrentIndexOfLevel(0);
            testSession=executeLevel(testSession,commandHelper,scanner);
        }
        }

        sessionHelper.remove(user);

        if (commandHelper.isEndExecution()) {
            sessionHelper.save(user, testSession);
            notification.notify(MsgKeys.SAVED_MSG);
        } else {
            String resultMsg = String.format("%s%s from %s",notification.getNotification(MsgKeys.RESULT_MSG), testSession.getSessionPoints(), testSession.totalQuestions());
            Output.printLineMsg(resultMsg);
            results.addResultsToFile(user, testSession);
        }
    }
    /**
     *
     */
     private TestSession executeLevel(TestSession testSession, CommandHelper commandHelper, Scanner scanner){

         while (testSession.hasNextInLevel() && !commandHelper.isEndExecution()) {
             testSession.getQuestion().askQuestion();
             System.out.println();
             String answer = scanner.nextLine();
             if (commandHelper.isCommand(answer)) {
                 commandHelper.execute(answer, testSession);
             } else {
                 testSession.setAnswer(answer);
                 testSession.nextQuestion();
             }
         }
         return testSession;
     }

     private boolean checkLevelPassed(TestSession levelSession){
         int levelPoints = levelSession.countCorrect();
         return levelPoints >= MIN_LEVEL_POINTS;
     }




    /**
     * Метод возвращает готовую сессию для пользователя
     * @param user  пользователь прошедший авторизацию
     * @param scanner сканер
     * @param sessionHelper инструментарий для сессии
     * @param createSession создавать ли сессию?
     * @return сессия для пользователя
     * @throws IOException
     */
    private TestSession getTestSession(User user, Scanner scanner, SessionHelper sessionHelper, boolean createSession) throws IOException {
        TestSession testSession;
        if (createSession) {
            int fromFile;
            do {
                notification.notify(MsgKeys.CHOISE_MSG);
                fromFile = Integer.valueOf(scanner.nextLine());
            } while ((fromFile != 1) && (fromFile != 2));

            Question[] questions = QuestionsFactory.getSource(fromFile).getQuestions();
            testSession = new TestSession(questions);
            notification.notify(MsgKeys.NEW_SESSION_MSG);
        } else {
            Question[] questions =  QuestionsFactory.getSource(1).getQuestions();
            testSession = sessionHelper.get(user,questions);
            notification.notify(MsgKeys.LOAD_SESSION_MSG);
        }
        return testSession;
    }

    /**
     * Метод проверяет нужно ли создавать новую сессию
     *
     * @param scanner сканер
     * @param hasSession - проверка не закончилась ли предыдущая сессия
     * @return нужно ли создавать сессию
     */
    private boolean isCreatedSession(Scanner scanner, boolean hasSession) {
        boolean createSession = true;
        if (hasSession) {
            notification.notify(MsgKeys.SAVE_MSG);
            String load;
            do {
                notification.notify(MsgKeys.YES_NO_MSG);
                load = scanner.nextLine();
            } while ((!load.equals("yes")) && (!load.equals("no")));
            switch (load) {
                case "yes":
                    createSession = false;
                    break;
                case "no":
                    createSession = true;
                    break;
            }
        }
        return createSession;
    }
}